#include "config_file.h"
#include <algorithm>
#include <iostream>
#include <cmath>
#include "types.h"
#include "misc.h"
#include "str_util.h"
	
namespace herm{

ConfigFileException::ConfigFileException(const std::string& file, int line, const std::string& func, const std::string desc)
	: Exception(file, line, func, 0, 0, desc)
{
}

ConfigFile::ConfigFile(const std::string& fileName, bool isPath)
{
    std::string path;
    if (!isPath)
    {
        path = herm::GetModulePath();
        path += fileName;
    }
    else
        path = fileName;
	m_path = path;

	std::ifstream file(path.c_str());
    if (!file.is_open())
    {
        std::string desc = "Open config file[";
        desc += fileName;
        desc += "] failed";
        throw HERM_CONFIG_FILE_EXCEPTION(desc);
    }

	std::string str;
    while (getline(file, str))
    {
		if (str.size() == 0)
			continue;
        // begin "#" is comments
        if (str.substr(0, 1) == "#" || str == " ")
            continue;

        size_t pos = str.find_first_of("=");
        std::string name = str.substr(0, pos);
        std::string val = str.substr(pos + 1);

        // erase " " and change to lower
        pos = name.find_first_not_of(" ");
        name = name.substr(pos);
        pos = name.find_last_not_of(" ");
        name = name.substr(0, pos + 1);
//        std::transform(name.begin(), name.end(), name.begin(), tolower);

		if (!val.empty() && val != " ")
		{
			pos = val.find_first_not_of(" ");
			val = val.substr(pos);
			pos = val.find_last_not_of(" ");
			val = val.substr(0, pos + 1);
		 // std::transform(val.begin(), val.end(), val.begin(), tolower);
		}
		else
		{
			val = "";
		}

        m_name2Vals.insert(std::make_pair(name, val));
    }
}
  
std::string ConfigFile::GetStrValue(const std::string& name) const
{
    std::string tmpName = name;
//    std::transform(tmpName.begin(), tmpName.end(), tmpName.begin(), tolower);
    Name2Values::const_iterator it = m_name2Vals.find(tmpName);
    if (it != m_name2Vals.end())
        return it->second;

	std::string desc = "Get the value of name: ";
	desc += name;
	desc += " failed";
    throw HERM_CONFIG_FILE_EXCEPTION(desc);
}

unsigned int ConfigFile::GetIntValue(const std::string& name) const
{
    std::string strVal = GetStrValue(name);
    std::istringstream iss(strVal);
    int intVal;
    iss >> intVal;

    return intVal;
}

void ConfigFile::SetStrValue(const std::string& name, const std::string& val)
{
	auto it = m_name2Vals.find(name);
	if (it != m_name2Vals.end())
	{
		it->second = val;
	}
	else
		m_name2Vals.insert(std::make_pair(name, val));
}

void ConfigFile::SetIntValue(const std::string& name, int val)
{
	std::string strVal = herm::IntToStr(val);
	SetStrValue(name, strVal);
}

void ConfigFile::Save()
{
	std::ofstream file(m_path);
	for (auto it = m_name2Vals.begin(); it != m_name2Vals.end(); ++it)
	{
		file << it->first << " = " << it->second << std::endl;
	}
}
} // end namespace herm{
